<template>
	<baseDialog ref="dialogRef" :title="dialogTitle" width="600px" @confirm="handleSubmit" @close="handleClose">
		<el-form ref="formRef" :model="formData" label-width="100px" :rules="rules">
			<el-form-item label="角色名称：" prop="name">
				<div class="w-80">
					<el-input v-model="formData.name" placeholder="请输入角色名称" clearable />
				</div>
			</el-form-item>
			<el-form-item label="角色描述：" prop="desc">
				<div class="w-80">
					<el-input v-model="formData.desc" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
				</div>
			</el-form-item>
			<el-form-item label="排序：" prop="sort">
				<div class="w-20">
					<el-input-number v-model="formData.sort" :min="0" :max="9999" controls-position="right" placeholder="请输入排序" />
				</div>
			</el-form-item>
			<el-form-item label="状态：" prop="disable">
				<el-radio-group v-model="formData.disable">
					<el-radio :label="0">正常</el-radio>
					<el-radio :label="1">禁用</el-radio>
				</el-radio-group>
			</el-form-item>
			<el-form-item label="菜单权限：" prop="menu_id">
				<div class="w-80">
					<el-checkbox label="展开/折叠" @change="handleExpand" />
					<el-checkbox label="全选/不全选" @change="handleSelectAll" />
					<el-tree
						ref="treeRef"
						:data="menuData.data"
						:props="menuData.props"
						node-key="id"
						:default-expand-all="menuData.isExpand"
						show-checkbox
						class="menu-data-tree"
					/>
				</div>
			</el-form-item>
		</el-form>
	</baseDialog>
</template>

<script setup lang="ts" name="authRoleEdit">
import { ref, shallowRef, reactive, computed, onMounted, nextTick } from 'vue';
import type { FormInstance } from 'element-plus';
import { roleDetail, roleAdd, roleEdit } from '/@/api/auth/role';
import { menuAll } from '/@/api/auth/menu';

const dialogRef = ref(null);

const dialogType = ref('add');

const dialogTitle = computed(() => {
	return dialogType.value == 'add' ? '添加角色' : '编辑角色';
});

const emit = defineEmits(['submit', 'close']);

const treeRef = ref(null);

const formRef = shallowRef<FormInstance>();

const formData = reactive({
	id: 0,
	name: '',
	desc: '',
	sort: 0,
	disable: 0,
	menu_id: [],
});

const menuData = reactive({
	data: [],
	isExpand: false,
	props: {
		children: 'children',
		label: 'name',
	},
});

const rules = reactive({
	name: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
});

const getMenuList = async () => {
	menuData.data = await menuAll();
	nextTick(() => {
		setMenuCheckedKeys();
	});
};

// 菜单展开折叠
const handleExpand = (check: any) => {
	if (check) {
		Object.values(treeRef.value.store.nodesMap).forEach((v: any) => v.expand());
	} else {
		Object.values(treeRef.value.store.nodesMap).forEach((v: any) => v.collapse());
	}
};

// 菜单选中未选
const handleSelectAll = (check: any) => {
	if (check) {
		treeRef.value?.setCheckedKeys(menuData.data.map((item) => item.id));
	} else {
		treeRef.value?.setCheckedKeys([]);
	}
};

// 获取权限菜单选中和半选中的节点
const getAllCheckedKeys = () => {
	const checkedKeys = treeRef.value?.getCheckedKeys();
	const halfCheckedKeys = treeRef.value?.getHalfCheckedKeys();
	checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
	return checkedKeys;
};

const handleSubmit = async () => {
	await formRef.value?.validate(async (valid: boolean) => {
		if (!valid) return;
		formData.menu_id = getAllCheckedKeys();
		dialogType.value == 'add' ? await roleAdd(formData) : await roleEdit(formData);
		dialogRef.value?.close();
		emit('submit');
	});
};

const setFormData = async (row: any, callback: any) => {
	const data = await roleDetail({
		id: row.id,
	});

	for (const key in formData) {
		if (data[key] != null && data[key] != undefined) {
			formData[key] = data[key];
		}
	}

	callback();
};

const setMenuCheckedKeys = () => {
	formData.menu_id.forEach((item) => {
		nextTick(() => {
			treeRef.value?.setChecked(item, true, false);
		});
	});
};

const handleClose = () => {
	emit('close');
};

const open = (type = 'add') => {
	dialogType.value = type;
	dialogRef.value?.open();
};

onMounted(() => {
	getMenuList();
});

defineExpose({
	open,
	setFormData,
});
</script>
<style scoped lang="scss">
.menu-data-tree {
	width: 100%;
	border: 1px solid var(--el-border-color);
	border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
	padding: 5px;
}
</style>
